<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram - Circular Motion</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>

<canvas id="physicsCanvas" width="500" height="450"></canvas>

<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // Style settings
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2;
    ctx.font = 'italic 18px Times New Roman';

    // Center point and dimensions
    const cx = 250;
    const cy = 250;
    const rx = 150; // horizontal radius of the disk
    const ry = 45;  // vertical radius for perspective
    const diskHeight = 50;

    // Function to draw dashed lines
    function drawDashedLine(x1, y1, x2, y2, dash = [5, 5]) {
        ctx.save();
        ctx.setLineDash(dash);
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
        ctx.restore();
    }

    // --- Start Drawing ---

    // 1. Draw the Turntable (Disk)
    // Shaded side of the cylinder
    ctx.beginPath();
    const bottomY = cy + diskHeight;
    ctx.moveTo(cx - rx, cy);
    ctx.lineTo(cx - rx, bottomY);
    ctx.ellipse(cx, bottomY, rx, ry, 0, Math.PI, 0, false);
    ctx.lineTo(cx + rx, cy);
    // Use arc to complete the path along the top ellipse edge for proper filling
    ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI, true);
    ctx.closePath();
    ctx.fillStyle = '#E0E0E0'; // Light gray fill
    ctx.fill();
    ctx.stroke();

    // Top surface of the disk
    ctx.beginPath();
    ctx.ellipse(cx, cy, rx, ry, 0, 0, 2 * Math.PI);
    ctx.fillStyle = 'white';
    ctx.fill();
    ctx.stroke();

    // 2. Draw the Axis of Rotation
    const axisTopY = cy - ry - 80;
    drawDashedLine(cx, axisTopY, cx, cy, [6, 4]);

    // 3. Draw the Rotation Arrow
    ctx.save();
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    const arrowCenterY = cy - ry - 35;
    const arrowRadius = 35;
    const startAngle = Math.PI * 1.3;
    const endAngle = Math.PI * 1.9;
    ctx.arc(cx, arrowCenterY, arrowRadius, startAngle, endAngle);
    ctx.stroke();

    // Arrowhead
    const arrowX = cx + arrowRadius * Math.cos(endAngle);
    const arrowY = arrowCenterY + arrowRadius * Math.sin(endAngle);
    ctx.beginPath();
    ctx.moveTo(arrowX, arrowY);
    ctx.lineTo(arrowX - 10, arrowY - 6);
    ctx.lineTo(arrowX - 12, arrowY + 4);
    ctx.closePath();
    ctx.fillStyle = 'black';
    ctx.fill();
    ctx.restore();

    // 4. Draw the sand accumulation path (dashed circle)
    const sandRx = rx * 0.7;
    const sandRy = ry * 0.7;
    drawDashedLine(0,0,0,0); // Hack to reset line dash in some environments if needed
    ctx.save();
    ctx.setLineDash([6, 4]);
    ctx.beginPath();
    ctx.ellipse(cx, cy, sandRx, sandRy, 0, 0, 2 * Math.PI);
    ctx.stroke();
    ctx.restore();

    // 5. Draw the radius 'r' and coordinate indicators at the center
    // Vertical and horizontal dashed lines from the center
    drawDashedLine(cx, cy, cx, cy - 25, [6, 4]);
    drawDashedLine(cx, cy, cx + 45, cy, [6, 4]);

    // The radius line 'r'
    const rAngle = -Math.PI / 6;
    const rEndX = cx + sandRx * Math.cos(rAngle);
    const rEndY = cy + sandRy * Math.sin(rAngle);
    drawDashedLine(cx, cy, rEndX, rEndY, [6, 4]);

    // The radius label 'r'
    ctx.fillText('r', cx + 0.6 * sandRx * Math.cos(rAngle), cy + 0.8 * sandRy * Math.sin(rAngle));

    // 6. Draw the Funnel
    const funnelX = cx + 115;
    const funnelTopY = cy - ry - 65;
    const funnelWidth = 60;
    const funnelMouthRy = 10;
    const funnelHeight = 55;
    const spoutHeight = 45;
    const spoutWidth = 8;
    const funnelBottomY = funnelTopY + funnelHeight;

    // Funnel Cone
    ctx.beginPath();
    ctx.moveTo(funnelX - funnelWidth / 2, funnelTopY);
    ctx.lineTo(funnelX - spoutWidth / 2, funnelBottomY);
    ctx.moveTo(funnelX + funnelWidth / 2, funnelTopY);
    ctx.lineTo(funnelX + spoutWidth / 2, funnelBottomY);
    ctx.stroke();

    // Spout
    ctx.beginPath();
    ctx.moveTo(funnelX - spoutWidth / 2, funnelBottomY);
    ctx.lineTo(funnelX - spoutWidth / 2, funnelBottomY + spoutHeight);
    ctx.moveTo(funnelX + spoutWidth / 2, funnelBottomY);
    ctx.lineTo(funnelX + spoutWidth / 2, funnelBottomY + spoutHeight);
    ctx.stroke();
    
    // Funnel Top Ellipse (drawn last to be on top)
    ctx.beginPath();
    ctx.ellipse(funnelX, funnelTopY, funnelWidth / 2, funnelMouthRy, 0, 0, 2 * Math.PI);
    ctx.fillStyle = 'white'; // White fill to obscure background lines
    ctx.fill();
    ctx.stroke();

    // Sand in the funnel
    ctx.save();
    ctx.lineWidth = 2.5;
    ctx.lineCap = 'round';
    ctx.beginPath();
    ctx.moveTo(funnelX - 22, funnelTopY - 1);
    ctx.bezierCurveTo(funnelX - 10, funnelTopY + 5, funnelX + 5, funnelTopY - 5, funnelX + 22, funnelTopY + 2);
    ctx.moveTo(funnelX - 15, funnelTopY - 4);
    ctx.bezierCurveTo(funnelX, funnelTopY, funnelX + 10, funnelTopY - 8, funnelX + 18, funnelTopY - 3);
    ctx.stroke();
    ctx.restore();

    // 7. Draw the Text Label
    ctx.font = '24px STSong'; // Use a font that supports Chinese characters
    ctx.fillStyle = 'black';
    ctx.textAlign = 'center';
    ctx.fillText('习题 3-17 图', cx, canvas.height - 30);
</script>

</body>
</html>